/*
 ####        # 
 #           #
 ## ### #  # #
 #  #-# #\ # #
 #  # # # \# ####
 Author: Felipe de Andrade Neves Lavratti

 Copyright: There are no restrictions. Use as you want.	  
*/

/*
	LPC 2478
	+ TFT DISPLAY
	+ TOUCH PANNEL
	+ SWIM
	+ SDRAM

	Get more at: selivre.wordpress.com
*/
/*
   Since the Touch Screen code is more complicated, I have commented it properly.
										  */

/* 
	These functions are appropriated only for resistive touch panel, with 4 wires (Y UP, Y DOWN, X LEFT and X RIGHT).
	
	The touch panel conception is two resistive layers separated by an isolating layer, that when pressed, one resistive
	layer will touch the other.

	To detect touch it is necessary to do the following:
	1st -> Polarize one layer (X or Y), by applying 5V in one side and 0V on the other.
	       This layer will present a voltage gradient from 5V to 0V.
	2nd -> Leave the other layer open collector in one side, while grounded on the other.
	       So that, if the user press the screen, the open collector layer will touch a polarized layer, capturing
	       the voltage magnitude from the other layer, if AD converted this voltage (at the opened collector terminal)
	       the system will know where TPannel has been pressed in one coordinate.
	3rd -> Repeat the Step 1 and 2 swapping the polarized layer for the open collector one. Then both coordinate
	       values will have been captured.

	How to detect if no press has happened?
	1- Polarize one layer
	2- Pre Charge the other  (Apply 5V then leave it open collector)
	3- ADC the Pre charged layer, if it is still charged, then no touch has happened.
	4- Repeat 1,2 and 3 swapping the polarized for the pre charged for robustness. 

	How to detect if the user has stopped touching?
	1- Polarize one layer.
	2- Open collector one side of the other layer, ground the other. Read voltage at the open collector side.
	   If it is different of 0V, then user is still touching.
																*/

									

#include "touchscreen.h"

// Polarize (X1=0V X2=3.3V)
void polarizexX(void)
{
	//P0.25, P0.23
	PINSEL1 &= ~(0xCC000);
   	FIO0DIR |= 0x1<<23; //P0.23 output
    	FIO0DIR |= 0x1<<25; //P0.25 output

	PINMODE1 |= 0x220000; PINMODE1 &= ~0x110000;   //P0x24 P0x26 no pulls

	FIO0SET = 0x1<<26; //Set P0.26
	FIO0SET = 0x1<<24; //Set P0.24
	FIO0SET = 0x1<<25; //Set P0.25
	FIO0SET = 0x1<<23; //Set P0.23
	FIO0CLR = 0x1<<26; //Clr P0.26
	FIO0CLR = 0x1<<24; //Clr P0.24
	FIO0CLR = 0x1<<25; //Clr P0.25
	FIO0CLR = 0x1<<23; //Clr P0.23 X0 = 0V

	FIO0SET = 0x1<<25; //Set P0.25 X1 = 5V

}

// Polarize (X1=3.3V X2=0V)
void polarizeXx(void)
{


	//P0.23, P0.25
	PINSEL1 &= ~(0xCC000);
	FIO0DIR|= 0x1<<23; //P0.23 output
	FIO0DIR |= 0x1<<25; //P0.25 output
	
	PINMODE1 |= 0x220000; PINMODE1 &= ~0x110000;   //P0x24 P0x26 no pulls

	FIO0SET = 0x1<<26; //Set P0.26
	FIO0SET = 0x1<<24; //Set P0.24
	FIO0SET = 0x1<<25; //Set P0.25
	FIO0SET = 0x1<<23; //Set P0.23
	FIO0CLR = 0x1<<26; //Clr P0.26
	FIO0CLR = 0x1<<24; //Clr P0.24
	FIO0CLR = 0x1<<25; //Clr P0.25 X1= 0V
	FIO0CLR = 0x1<<23; //Clr P0.23 

	FIO0SET = 0x1<<23; //Set P0.23 X0 = 5V
}

// Polarize (Y1=0V Y2=3.3V)
void polarizeyY(void)
{
	//P0.26, P0.24
	PINSEL1 &= ~(0x330000);
	FIO0DIR |= 0x1<<26; //P0.26 output
	FIO0DIR |= 0x1<<24; //P0.24 output

	PINMODE1 |= 0x88000; PINMODE1 &= ~0x44000;   //P0x23 P0x25 no pulls

	FIO0SET = 0x1<<26; //Set P0.26
	FIO0SET = 0x1<<24; //Set P0.24
	FIO0SET = 0x1<<25; //Set P0.25
	FIO0SET = 0x1<<23; //Set P0.23
	FIO0CLR = 0x1<<26; //Clr P0.26
	FIO0CLR = 0x1<<24; //Clr P0.24
	FIO0CLR = 0x1<<25; //Clr P0.25
	FIO0CLR = 0x1<<23; //Clr P0.23

	FIO0SET = 0x1<<26; //Set P0.26

}
// Polarize (Y1=3.3V Y2=0V)
void polarizeYy(void)
{
	//P0.24, P0.26
	PINSEL1 &= ~(0x330000);
	FIO0DIR |= 0x1<<26; //P0.26 output
	FIO0DIR |= 0x1<<24; //P0.24 output

	PINMODE1 |= 0x88000; PINMODE1 &= ~0x44000;   //P0x23 P0x25 no pulls

	FIO0SET = 0x1<<26; //Set P0.26
	FIO0SET = 0x1<<24; //Set P0.24
	FIO0SET = 0x1<<25; //Set P0.25
	FIO0SET = 0x1<<23; //Set P0.23
	FIO0CLR = 0x1<<26; //Clr P0.26
	FIO0CLR = 0x1<<24; //Clr P0.24
	FIO0CLR = 0x1<<25; //Clr P0.25
	FIO0CLR = 0x1<<23; //Clr P0.23


	FIO0SET = 0x1<<24; //Set P0.24
}
/*
	Check if user is still touching
*/
int TSGetDetouch()
{
	int sample;

	InitADC(TS_Y_CHANNEL_0);
	polarizeXx();
	FIO0DIR |= 0x1<<26; //P0.26 output
	FIO0CLR = 0x1<<26;  //Clr P0.26
//	delayMs(TS_DELAY);
	sample = GetADC(TS_Y_CHANNEL_0);
	sample += GetADC(TS_Y_CHANNEL_0);
	sample += GetADC(TS_Y_CHANNEL_0);
	if (sample <= TOUCH_DETECT_TOLERANCE )
	{
		return 1; //detouch happened
	}
	else
	{
		return 0; //user still touching
	}
}

/*
	Check if touch has happened.
*/
int touch(UNS_32 *sample)
{
	int i;
	UNS_32 sample_temp;

	// Tpanel is already polarizedXx.

	FIO0DIR &= ~(0x1<<26); //P0.26 input
	sample[0] = 0;
	for(i=0; i<10; i++) //200 for filtering noise
	{
		sample[0] += GetADC(TS_Y_CHANNEL_0);
	}
	sample[0] /= 10;

	//check if touch is still there, system should sample both coordinates in time.
	if (TSGetDetouch()) return 0;


	InitADC(TS_X_CHANNEL_0);
	polarizeYy();
	FIO0DIR &= ~(0x1<<25); //P0.25 input
//	delayMs(TS_DELAY);

	sample[1] = 0;
	for(i=0; i<10; i++) //200 for filtering noise
	{
		sample[1] += GetADC(TS_X_CHANNEL_0);
	}
	sample[1] /= 10;

	//Both coordinates has been sampled.

	return 1;

}
/*
	This is the Touch Screen Get Touch function.
*/
int  TSGetTouch(UNS_32 timeout_time, touchscreen_data *ts)
{
	char str[100];
	int ydif, xdif;

	UNS_32 sample[2];
	static UNS_32 x_min=X_MIN,
			      x_max=X_MAX,
			      y_min=Y_MIN,
			      y_max=Y_MAX;

	timeoutMs(timeout_time, START); 				//Starts the clock for timeout check

	while(timeoutMs(0,CHECK_IF_MATCH) != MATCH) 			//Wile not timeout
	{
		InitADC(TS_Y_CHANNEL_0);				//Setup: Y0 for reading
		polarizeXx();						//Setup: X layer polarized
		FIO0DIR |= 0x1<<26; //P0.26 output			//Setup: Y1 = gnd
		FIO0CLR = 0x1<<26;  //Clr P0.26
//		delayMs(TS_DELAY);					//Wait TS_DELAY for the GPIO and ADC get ready.
		sample[0] = GetADC(TS_Y_CHANNEL_0);			//Pre sample 3 times to detect if a touch happened.
		sample[0] += GetADC(TS_Y_CHANNEL_0);
		sample[0] += GetADC(TS_Y_CHANNEL_0);
		sample[0] /= 3;
		FIO0SET = 0x1<<26;  //Set P0.26				//Charge Y layer, Don't remember the reason.

		if (sample[0] > TOUCH_DETECT_TOLERANCE )		//If touch happened
		{
			//sample[0] += GetADC(TS_Y_CHANNEL_0);		//Well, Y is charged, sample[0] will be near the top.
//			if (sample[0] > TOUCH_DETECT_TOLERANCE )	//Always enter here. I don't remember why I did this.
//			{
				if (touch(sample))			//Get X and Y coordinate of the touch.
				{
							//Auto Calibrate the Minimum and Maximum values on the go,
									//and write it to the provided struct, in form of LCD pixels coordinates.
						if(sample[0] < x_min && sample[0] > TOUCH_DETECT_TOLERANCE ) x_min= sample[0];
						else if(sample[0] > x_max) x_max= sample[0];
						if(sample[1] < y_min && sample[1] > 100 ) y_min= sample[1];
						else if(sample[1] > y_max) y_max= sample[1];

						ts->xlast=ts->x;
						ts->ylast=ts->y;
						ts->x = (sample[0] - x_min)*X_LCD_RESOLUTION/(x_max-x_min);
						ts->y = (sample[1] - y_min)*Y_LCD_RESOLUTION/(y_max-y_min);

						if(ts->x >= ts->xlast) xdif = ts->x - ts->xlast;
						else xdif = ts->xlast - ts->x;
						if(ts->y >= ts->ylast) ydif = ts->y - ts->ylast;
						else ydif = ts->ylast - ts->y;

						if(xdif > ydif) ts->touchradius = xdif;
						else ts->touchradius = ydif;

//						sprintf(str,"X: m%d M%d, Y:m%d M%d, S:%d %d, D:%d %d,\n",x_min, x_max, y_min, y_max,sample[0], sample[1], ts->x, ts->y );
//						UARTTransmitString(str, UART_CH_0);



						return 1;
				}
//			}
		}							//Else no touch happened - Return 0
	}
    ts->xlast=-1;
	ts->ylast=-1;
	ts->touchradius = -1;
return 0;
}

